import requests
import json

import sys
sys.path.append('..')
from utils.TimeStampUtils import date_to_timestamp, timestamp_to_date
from model.CIInfo import CIInfo

# 此函数用于将普通日期转换为CI网站特定的时间戳格式（2024/09/22 -> 2024-09-22 08:00:00 -> timestamp）
def date_2_timestamp_wrapper(date):
    date = date.replace('/', '-')
    # 拼接字符串
    date += ' 08:00:00'
    return date_to_timestamp(date)

# 全局常量
vulnerabilityType = {0:'有效漏洞', 1: '非漏洞', 2: '重复漏洞', 3: '漏洞详情缺失', 4: '误报', 5: '漏洞已修改', 6: '其他'}
headers = {
    "Cookie" : "token=BQCTAdlus3jTCBmX+SUNOhot+3/vLjTlgL7zW+IZtbUPYUaHPKU0Xl3mjjpQI7hqk+GeUTA8lizf5FeASRsH1yH1dCACKrJv0JUpKq8g2QH/0izQBRZ+SOYbnAp8ojjOuXmOAE3b89ADfKTZCn5kWFE8sC+wraFevgbkZtru1vbid16xn4rhwbkbwXaIgpVBSCAKEYqww6tj+j0pdldstG7LrPsrpdXqt1bdjmch0rqn2LkUZJUX062xR05h4UGInJk57eTLISRu/wL1w8fGaSMo1458fT81x1081A7qJX3jVtRc9/qrDkKsKG5iGNvQK4ARKkTK761EkSPqUca/Og1g9VPGWNjfP0KFIwJtnetSaK4g+zeCg7aUjqKUmTRwsw4aNkTk+qG1WVTVvvRF3h74exorY8V27h5ZOGkoG74wL35jESrV7UKoj0ZXY3+eP5QhzAiR1KVc7kQgWh2ANrdhbAsMBHjBCFhPgYSW/2Y1YWMzZDI5LTg4NTAtNDAzZi1hNzY4LTJiYTM4YTFkZmI1YgAAAAAVFBMSERAPDg0MCwoJCAcGBQQDAgE60anMsYeHeDJYv2ZB/GT7wsRZZmQoxySTXWKdowo/fA==; _frid=8a21010d7fed4ed2ab3bc98785758bc8; HWWAFSESID=0fc15768f23e744065; HWWAFSESTIME=1725516636873; _fr_ssid=53a3007e3f5f4dccbb1f4b22f9151ebc; _fr_pvid=28bc6b8c710e454cbce066a3739bcf44",
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",     
}
# json 解析工具
json2PageSize = ['data', 'pageSize']
json2TotalSize = ['data', 'totalSize']
json2CVEList = ['data', 'dataList']
cveList2InternalId = ['internalId']
cveList2CVE = ['cveId']
cveList2CreateTime = ['createTime']
cveList2ExpirationTime = ['expirationDate']
cveList2Type = ['vulnerabilityType']
def jsonElement(json, keys):
    ret = json
    for key in keys:
        ret = ret[key]
    return ret

########################public 函数##############################################
def getTypeAndReason(cve):
    resp = _searchCVE('https://ci.openharmony.cn/api/opensoftware/vulnerability/analyze/1', cve=cve)
    j = json.loads(resp)
    reason = _getAnalyzeReason(_getInternalId(j))
    _type = _getVulnerabilityType(j)
    _stage = _getProcessStage(j)
    return {"type": _type, "reaseon": reason, "processStage": _stage}


# 分支排查阶段
def getBranchDetermineInfo(startExpirationDate, endExpirationDate):
    cve_list = []
    startExpirationDate = date_2_timestamp_wrapper(startExpirationDate)
    endExpirationDate = date_2_timestamp_wrapper(endExpirationDate)
    # cookie到期后 会提示401

    # data不对的话 会提示service error
    data = {
        "internalId": None,
        "cveId": None,
        "repoName": None,
        "versionNum": None,
        "branch": None,
        "influence": None,
        "processStage": 0,
        "investigateTime": None,
        "createTime": None,
        "investigateOwner": None,
        "startInvestigateTime": None,
        "endInvestigateTime": None,
        "startCreateTime": None,
        "endCreateTime": None,
        "updateTime": None,
        "sortField": "",
        "sortType": "DESC",
        "type": 0,
        "startExpirationDate": 1727136000000,
        "endExpirationDate": 1728864000000,
        "pageSize": 1,
        "currentPage": 1,
        "totalSize": 1
    }
    resp = requests.post('https://ci.openharmony.cn/api/opensoftware/vulnerability/investigate/about_me', headers=headers, json=data)
    print(resp.text)
    j = resp.json()
    totalSize = jsonElement(j, json2TotalSize)
    data['pageSize'] = totalSize
    resp = requests.post('https://ci.openharmony.cn/api/opensoftware/vulnerability/investigate/about_me', headers=headers, json=data)
    j = resp.json()
    cveList = jsonElement(j, json2CVEList)
    for cve in cveList:
        cveId = jsonElement(cve, cveList2CVE)
        internalId = jsonElement(cve, cveList2InternalId)
        createTime = timestamp_to_date(jsonElement(cve, cveList2CreateTime))
        expirationTime = timestamp_to_date(jsonElement(cve, cveList2ExpirationTime))
        # type = jsonElement(cve, cveList2Type)
        cve_list.append(CIInfo(cveId, None, None, createTime, None, expirationTime, internalId))
    return cve_list

# 漏洞分析阶段
def getCIInfoList(startExpirationDate, endExpirationDate):
    cve_list = []
    startExpirationDate = date_2_timestamp_wrapper(startExpirationDate)
    endExpirationDate = date_2_timestamp_wrapper(endExpirationDate)

    data = {
        "internalId":None,
        "repoName":None,
        "versionNum":None,
        "processStage":[],
        "cveId": None,
        "vulnSource":None,
        "vulnOwner":None,
        "createTime":None,
        "expirationDate":None,
        "startExpirationDate":str(startExpirationDate),
        "endExpirationDate":str(endExpirationDate),
        "startCreateTime":None,
        "endCreateTime":None,
        "sortField":"",
        "sortType":"DESC",
        "pageSize":1,
        "currentPage":1,
        "totalSize":1,
        "type":1}
    resp = requests.post('https://ci.openharmony.cn/api/opensoftware/vulnerability/analyze/2', headers=headers, json=data)
    j = resp.json()
    totalSize = jsonElement(j, json2TotalSize)
    data['pageSize'] = totalSize
    resp = requests.post('https://ci.openharmony.cn/api/opensoftware/vulnerability/analyze/2', headers=headers, json=data)
    j = resp.json()
    cveList = jsonElement(j, json2CVEList)
    for cve in cveList:
        cveId = jsonElement(cve, cveList2CVE)
        internalId = jsonElement(cve, cveList2InternalId)
        createTime = timestamp_to_date(jsonElement(cve, cveList2CreateTime))
        expirationTime = timestamp_to_date(jsonElement(cve, cveList2ExpirationTime))
        type = jsonElement(cve, cveList2Type)
        cve_list.append(CIInfo(cveId, vulnerabilityType[type], None, createTime, None, expirationTime, internalId))
    return cve_list

# 漏洞分析阶段 ：用于拒绝一个cve ！！！（仅仅适用于表格中状态为不涉及的cve，不能用于之前已合入的类型）从漏洞分析阶段进入到专家审核阶段，拒绝类型为误报
def refuse_cve(cve_id, cve_refuse_reason):
    if cve_id == "" or cve_id is None:
        raise ValueError("cve_id is empty")
    analyzeInfo = get_analyzeInfo(cve_id)['analyze']
    # pprint.pprint(analyzeInfo)
    analyzeId = analyzeInfo['id']
    processStage = analyzeInfo['processStage']
    cvssvBasescore = analyzeInfo['cvssvBasescore']
    cvssvVector = analyzeInfo['cvssvVector']
    operation_data = make_opration_data(analyzeId=analyzeId, processStage=processStage, 
                                        cvssvBasescore=cvssvBasescore, cvssvVector=cvssvVector, analyzeReason=cve_refuse_reason)
    return do_opration(operation_data)



########################private 函数##############################################
def _searchCVE(url, cve):
    data = {"internalId":None,
     "repoName":None,
     "versionNum":None,
     "processStage":[],
     "cveId": str(cve),
     "vulnSource":None,
     "vulnOwner":None,
     "createTime":None,
     "expirationDate":None,"startExpirationDate":None,"endExpirationDate":None,"startCreateTime":None,"endCreateTime":None,"sortField":"",
     "sortType":"DESC","pageSize":10,
     "currentPage":1,"totalSize":1,"type":1}
    response = requests.post(url, headers=headers, json=data)
    return response.text
vulnerabilityType = {0:'有效漏洞', 1: '非漏洞', 2: '重复漏洞', 3: '漏洞详情缺失', 4: '误报', 5: '漏洞已修改', 6: '其他'}
processStage = {0: '漏洞分析', 1: '专家打分1', 2: '专家打分2', 3: '专家审核', 4: '完成'}
def _getProcessStage(json):
    if len(json['data']['dataList']) == 0:
        return None
    return processStage[json['data']['dataList'][0]['processStage']]
def _getVulnerabilityType(json):
    if len(json['data']['dataList']) == 0:
        return None
    return vulnerabilityType[json['data']['dataList'][0]['vulnerabilityType']]
def _getInternalId(json):
    if len(json['data']['dataList']) == 0:
        return None
    return json['data']['dataList'][0]['internalId']
def _getAnalyzeReason(internalId):
    if internalId is None:
        return None
    resp = requests.get('https://ci.openharmony.cn/api/opensoftware/vulnerability/analyze/'+internalId, headers=headers).text
    dict = json.loads(resp)
    if len(dict['data']['details']) == 0:
        return None
    return dict['data']['details'][0]['analyzeReason']

def make_opration_data(analyzeId, processStage, cvssvBasescore, cvssvVector, analyzeReason):
    if analyzeReason is None or analyzeReason == '':
        raise ValueError("analyzeReason is empty")
    operation_data = {
        "analyzeId": int(analyzeId),
        "processStage": int(processStage),
        "type": 1,
        "vulnerabilityType": 4,
        "cvssvBasescore": float(cvssvBasescore),
        "cvssvVector": str(cvssvVector),
        "cwe": "",
        "reviewResult": 0,
        "analyzeReason": str(analyzeReason)
    }
    return operation_data
def get_analyzeInfo(cve_id):
    respText = _searchCVE('https://ci.openharmony.cn/api/opensoftware/vulnerability/analyze/2', cve_id)
    j = json.loads(respText)
    if str(j['code']) != '20000':
        raise RuntimeError("cve_id {} , search_error: {}".format(cve_id, j['message']))
    else :
        if j['data']['totalSize'] != 1:
            raise RuntimeError("{} not found".format(cve_id))
        else :
            internalId= _getInternalId(j)
            headers = {
                "Cookie" : "token=BQCTAdlus3jTCBmX+SUNOhot+3/vLjTlgL7zW+IZtbUPYUaHPKU0Xl3mjjpQI7hqk+GeUTA8lizf5FeASRsH1yH1dCACKrJv0JUpKq8g2QH/0izQBRZ+SOYbnAp8ojjOuXmOAE3b89ADfKTZCn5kWFE8sC+wraFevgbkZtru1vbid16xn4rhwbkbwXaIgpVBSCAKEYqww6tj+j0pdldstG7LrPsrpdXqt1bdjmch0rqn2LkUZJUX062xR05h4UGInJk57eTLISRu/wL1w8fGaSMo1458fT81x1081A7qJX3jVtRc9/qrDkKsKG5iGNvQK4ARKkTK761EkSPqUca/Og1g9VPGWNjfP0KFIwJtnetSaK4g+zeCg7aUjqKUmTRwsw4aNkTk+qG1WVTVvvRF3h74exorY8V27h5ZOGkoG74wL35jESrV7UKoj0ZXY3+eP5QhzAiR1KVc7kQgWh2ANrdhbAsMBHjBCFhPgYSW/2Y1YWMzZDI5LTg4NTAtNDAzZi1hNzY4LTJiYTM4YTFkZmI1YgAAAAAVFBMSERAPDg0MCwoJCAcGBQQDAgE60anMsYeHeDJYv2ZB/GT7wsRZZmQoxySTXWKdowo/fA==; _frid=8a21010d7fed4ed2ab3bc98785758bc8; HWWAFSESID=0fc15768f23e744065; HWWAFSESTIME=1725516636873; _fr_ssid=53a3007e3f5f4dccbb1f4b22f9151ebc; _fr_pvid=28bc6b8c710e454cbce066a3739bcf44",
                        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3",     
            }
            resp = requests.get('https://ci.openharmony.cn/api/opensoftware/vulnerability/analyze/'+internalId, headers=headers)
            #json pretty print
            analyzeInfo = json.loads(resp.text)
            if analyzeInfo['code'] != '20000':
                print("cve_id {} analyze_error: {}".format(cve_id, analyzeInfo['message']))
            return analyzeInfo['data']
def do_opration(data):
    resp = requests.post('https://ci.openharmony.cn/api/opensoftware/vulnerability/analyze/operation',
                  headers=headers, json=data)
    if json.loads(resp.text)['code'] != '20000':
        raise RuntimeError("{} 请求失败", data)
    return resp